using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Xml;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Xml.Linq;
using ModulesToolkit.Common;

namespace ModulesToolkit.Common
{
    public interface IConverter<T>
    {
        T Value
        {
            get;
        }
    }
    internal class Converter<T> : IConverter<T>
    {
        public T Value
        {
            get;
            protected set;
        }
        public Converter(T value)
        {
            this.Value = value;
        }
    }
}
namespace System.Reflection
{
    public static class ObjectExtensions
    {
        public static K FindTypeByRecursion<T, K>(this T item, Func<T, T> function)
            where T : class
            where K : class, T
        {
            while (!(item is K))
            {
                if ((item = function(item)) == null)
                {
                    return default(K);
                }
            }
            return (K)item;
        }
        public static object InvokeMethod(this object obj, string methodName, params object[] parameters)
        {
            return obj.InvokeMethod(methodName, parameters);
        }
        public static T InvokeMethod<T>(this object obj, string methodName, params object[] parameters)
        {
            Type type = obj.GetType();
            MethodInfo method = type.GetMethod(methodName);
            if (method == null)
            {
                throw new ArgumentException(string.Format("Method '{0}' not found.", methodName), methodName);
            }
            object obj2 = method.Invoke(obj, parameters);
            if (!(obj2 is T))
            {
                return default(T);
            }
            return (T)obj2;
        }
        public static object GetPropertyValue(this object obj, string propertyName)
        {
            return obj.GetPropertyValue<object>(propertyName, null);
        }
        public static T GetPropertyValue<T>(this object obj, string propertyName)
        {
            return obj.GetPropertyValue(propertyName, default(T));
        }
        public static T GetPropertyValue<T>(this object obj, string propertyName, T defaultValue)
        {
            Type type = obj.GetType();
            PropertyInfo property = type.GetProperty(propertyName);
            if (property == null)
            {
                throw new ArgumentException(string.Format("Property '{0}' not found.", propertyName), propertyName);
            }
            object value = property.GetValue(obj, null);
            if (!(value is T))
            {
                return defaultValue;
            }
            return (T)value;
        }
        public static void SetPropertyValue(this object obj, string propertyName, object value)
        {
            Type type = obj.GetType();
            PropertyInfo property = type.GetProperty(propertyName);
            if (property == null)
            {
                throw new ArgumentException(string.Format("Property '{0}' not found.", propertyName), propertyName);
            }
            if (!property.CanWrite)
            {
                throw new ArgumentException(string.Format("Property '{0}' does not allow writes.", propertyName), propertyName);
            }
            property.SetValue(obj, value, null);
        }
        public static T GetAttribute<T>(this object obj) where T : Attribute
        {
            return obj.GetAttribute<T>(true);
        }
        public static T GetAttribute<T>(this object obj, bool includeInherited) where T : Attribute
        {
            Type type = (obj as Type) ?? obj.GetType();
            object[] customAttributes = type.GetCustomAttributes(typeof(T), includeInherited);
            if (customAttributes.Length > 0)
            {
                return customAttributes[0] as T;
            }
            return default(T);
        }
        public static IEnumerable<T> GetAttributes<T>(this object obj) where T : Attribute
        {
            return obj.GetAttributes<T>();
        }
        public static IEnumerable<T> GetAttributes<T>(this object obj, bool includeInherited) where T : Attribute
        {
            return
                from attribute in ((obj as Type) ?? obj.GetType()).GetCustomAttributes(typeof(T), includeInherited).OfType<T>()
                select attribute;
        }
        public static bool IsOfType<T>(this object obj)
        {
            return obj.IsOfType(typeof(T));
        }
        public static bool IsOfType(this object obj, Type type)
        {
            return obj.GetType().Equals(type);
        }
        public static bool IsOfTypeOrInherits<T>(this object obj)
        {
            return obj.IsOfTypeOrInherits(typeof(T));
        }
        public static bool IsOfTypeOrInherits(this object obj, Type type)
        {
            Type type2 = obj.GetType();
            while (!type2.Equals(type))
            {
                if (type2 == type2.BaseType || type2.BaseType == null)
                {
                    return false;
                }
                type2 = type2.BaseType;
            }
            return true;
        }
        public static bool IsAssignableTo<T>(this object obj)
        {
            return obj.IsAssignableTo(typeof(T));
        }
        public static bool IsAssignableTo(this object obj, Type type)
        {
            Type type2 = obj.GetType();
            return type.IsAssignableFrom(type2);
        }
        public static T GetTypeDefaultValue<T>(this T value)
        {
            return default(T);
        }
        public static object DynamicCast(this object obj, Type targetType)
        {
            if (targetType.IsAssignableFrom(obj.GetType()))
            {
                return obj;
            }
            Type originType = obj.GetType();
            string[] names = new string[]
		{
			"op_Implicit", 
			"op_Explicit"
		};
            MethodInfo methodInfo = targetType.GetMethods(BindingFlags.Static | BindingFlags.Public).Union(originType.GetMethods(BindingFlags.Static | BindingFlags.Public)).FirstOrDefault((MethodInfo itm) => itm.ReturnType.Equals(targetType) && itm.GetParameters().Length == 1 && itm.GetParameters()[0].ParameterType.IsAssignableFrom(originType) && names.Contains(itm.Name));
            if (methodInfo != null)
            {
                return methodInfo.Invoke(null, new object[]
			{
				obj
			});
            }
            throw new InvalidOperationException(string.Format("No matching cast operator found from {0} to {1}.", originType.Name, targetType.Name));
        }
    }
}

namespace System.Data
{
    public static class ObjectExtensions
    {
        public static object ToDatabaseValue<T>(this T value)
        {
            if (!value.Equals(value.GetTypeDefaultValue<T>()))
            {
                return value;
            }
            return DBNull.Value;
        }
    }
}

namespace System.Linq.Xml
{
    public static class ObjectExtensions
    {
        public static XElement ToXElement(this object o, BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, int maxArrayElements = 5)
        {
            XElement result;
            try
            {
                result = ObjectExtensions.ToXElementInternal(o, new HashSet<object>(), flags, maxArrayElements);
            }
            catch
            {
                result = new XElement(o.GetType().Name);
            }
            return result;
        }
        private static XElement ToXElementInternal(object o, ICollection<object> visited, BindingFlags flags, int maxArrayElements)
        {
            if (o == null)
            {
                return new XElement("null");
            }
            if (visited.Contains(o))
            {
                return new XElement("cyclicreference");
            }
            if (!o.GetType().IsValueType)
            {
                visited.Add(o);
            }
            Type type = o.GetType();
            XElement xElement = new XElement(ObjectExtensions.CleanName(type.Name, type.IsArray));
            if (!ObjectExtensions.NeedRecursion(type, o))
            {
                xElement.Add(new XElement(ObjectExtensions.CleanName(type.Name, type.IsArray), string.Empty + o));
                return xElement;
            }
            if (o is IEnumerable)
            {
                int num = 0;
                foreach (object current in o as IEnumerable)
                {
                    Type type2 = current.GetType();
                    xElement.Add(ObjectExtensions.NeedRecursion(type2, current) ? ObjectExtensions.ToXElementInternal(current, visited, flags, maxArrayElements) : new XElement(ObjectExtensions.CleanName(type2.Name, type2.IsArray), current));
                    if (num++ >= maxArrayElements)
                    {
                        break;
                    }
                }
                return xElement;
            }
            foreach (PropertyInfo current2 in
                from propertyInfo in type.GetProperties(flags)
                where propertyInfo.CanRead
                select propertyInfo)
            {
                object value = ObjectExtensions.GetValue(o, current2);
                xElement.Add(ObjectExtensions.NeedRecursion(current2.PropertyType, value) ? new XElement(ObjectExtensions.CleanName(current2.Name, current2.PropertyType.IsArray), ObjectExtensions.ToXElementInternal(value, visited, flags, maxArrayElements)) : new XElement(ObjectExtensions.CleanName(current2.Name, current2.PropertyType.IsArray), string.Empty + value));
            }
            FieldInfo[] fields = type.GetFields();
            for (int i = 0; i < fields.Length; i++)
            {
                FieldInfo fieldInfo = fields[i];
                object value2 = fieldInfo.GetValue(o);
                xElement.Add(ObjectExtensions.NeedRecursion(fieldInfo.FieldType, value2) ? new XElement(ObjectExtensions.CleanName(fieldInfo.Name, fieldInfo.FieldType.IsArray), ObjectExtensions.ToXElementInternal(value2, visited, flags, maxArrayElements)) : new XElement(ObjectExtensions.CleanName(fieldInfo.Name, fieldInfo.FieldType.IsArray), string.Empty + value2));
            }
            return xElement;
        }
        private static bool NeedRecursion(Type type, object o)
        {
            return o != null && !type.IsPrimitive && (!(o is string) && !(o is DateTime) && !(o is DateTimeOffset) && !(o is TimeSpan) && !(o is Delegate) && !(o is Enum) && !(o is decimal)) && !(o is Guid);
        }
        private static object GetValue(object o, PropertyInfo propertyInfo)
        {
            object result;
            try
            {
                result = propertyInfo.GetValue(o, null);
            }
            catch
            {
                try
                {
                    result = propertyInfo.GetValue(o, new object[]
				{
					0
				});
                }
                catch
                {
                    result = null;
                }
            }
            return result;
        }
        private static string CleanName(IEnumerable<char> name, bool isArray)
        {
            StringBuilder stringBuilder = new StringBuilder();
            foreach (char current in
                from c in name
                where char.IsLetterOrDigit(c) && c != '`'
                select c)
            {
                stringBuilder.Append(current);
            }
            if (isArray)
            {
                stringBuilder.Append("Array");
            }
            return stringBuilder.ToString();
        }
    }
}

namespace System.Web.UI
{
    public static class ObjectExtensions
    {
        public static string ToStringDump(this object o, BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, int maxArrayElements = 5)
        {
            return ObjectExtensions.ToStringDumpInternal(o.ToXElement(flags, maxArrayElements)).Aggregate(string.Empty, (string str, string el) => str + el);
        }
        private static IEnumerable<string> ToStringDumpInternal(XContainer toXElement)
        {
            foreach (XElement current in
                from o in toXElement.Elements()
                orderby o.Name.ToString()
                select o)
            {
                if (current.HasElements)
                {
                    foreach (string current2 in ObjectExtensions.ToStringDumpInternal(current))
                    {
                        yield return "{" + string.Format("{0}={1}", current.Name, current2) + "}";
                    }
                }
                else
                {
                    yield return "{" + string.Format("{0}={1}", current.Name, current.Value) + "}";
                }
            }
            yield break;
        }
        public static string ToHTMLTable(this object o, BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, int maxArrayElements = 5)
        {
            return ObjectExtensions.ToHTMLTableInternal(o.ToXElement(flags, maxArrayElements), 0).Aggregate(string.Empty, (string str, string el) => str + el);
        }
        private static IEnumerable<string> ToHTMLTableInternal(XContainer xel, int padding)
        {
            yield return ObjectExtensions.FormatHTMLLine("<table>", padding);
            yield return ObjectExtensions.FormatHTMLLine("<tr><th>Attribute</th><th>Value</th></tr>", padding + 1);
            foreach (XElement current in
                from o in xel.Elements()
                orderby o.Name.ToString()
                select o)
            {
                if (current.HasElements)
                {
                    yield return ObjectExtensions.FormatHTMLLine(string.Format("<tr><td>{0}</td><td>", current.Name), padding + 1);
                    foreach (string current2 in ObjectExtensions.ToHTMLTableInternal(current, padding + 2))
                    {
                        yield return current2;
                    }
                    yield return ObjectExtensions.FormatHTMLLine("</td></tr>", padding + 1);
                }
                else
                {
                    yield return ObjectExtensions.FormatHTMLLine(string.Format("<tr><td>{0}</td><td>{1}</td></tr>", current.Name, HttpUtility.HtmlEncode(current.Value)), padding + 1);
                }
            }
            yield return ObjectExtensions.FormatHTMLLine("</table>", padding);
            yield break;
        }
        private static string FormatHTMLLine(string tag, int padding)
        {
            return string.Format("{0}{1}{2}", string.Empty.PadRight(padding, '\t'), tag, Environment.NewLine);
        }

    }
}

namespace System
{
    public static class ObjectExtensions
    {
        public static int CountLoopsToNull<T>(this T item, Func<T, T> function) where T : class
        {
            int num = 0;
            while ((item = function(item)) != null)
            {
                num++;
            }
            return num;
        }
        public static T CastAs<T>(this object obj) where T : class, new()
        {
            return obj as T;
        }
        public static T Clone<T>(this T source)
        {
            if (!typeof(T).IsSerializable)
            {
                throw new ArgumentException("The type must be serializable.", "source");
            }
            if (object.ReferenceEquals(source, null))
            {
                return default(T);
            }
            IFormatter formatter = new BinaryFormatter();
            Stream stream = new MemoryStream();
            T result;
            using (stream)
            {
                formatter.Serialize(stream, source);
                stream.Seek(0L, SeekOrigin.Begin);
                result = (T)formatter.Deserialize(stream);
            }
            return result;
        }
        public static T CastTo<T>(this object value)
        {
            return (T)value;
        }
        public static bool IsNull(this object target)
        {
            return target.IsNull<object>();
        }
        public static bool IsNull<T>(this T target)
        {
            return object.ReferenceEquals(target, null);
        }
        public static bool IsNotNull(this object target)
        {
            return target.IsNotNull<object>();
        }
        public static bool IsNotNull<T>(this T target)
        {
            return !object.ReferenceEquals(target, null);
        }
        public static string AsString(this object target)
        {
            if (!object.ReferenceEquals(target, null))
            {
                return string.Format("{0}", target);
            }
            return null;
        }
        public static string AsString(this object target, IFormatProvider formatProvider)
        {
            return string.Format(formatProvider, "{0}", new object[]
		{
			target
		});
        }
        public static string AsInvariantString(this object target)
        {
            return string.Format(CultureInfo.InvariantCulture, "{0}", new object[]
		{
			target
		});
        }
        public static T NotNull<T>(this T target, T notNullValue)
        {
            if (!object.ReferenceEquals(target, null))
            {
                return target;
            }
            return notNullValue;
        }
        public static T NotNull<T>(this T target, Func<T> notNullValueProvider)
        {
            if (!object.ReferenceEquals(target, null))
            {
                return target;
            }
            return notNullValueProvider();
        }
        public static bool EqualsAny<T>(this T obj, params T[] values)
        {
            return Array.IndexOf<T>(values, obj) != -1;
        }
        public static bool EqualsNone<T>(this T obj, params T[] values)
        {
            return !obj.EqualsAny(values);
        }
        public static T ConvertTo<T>(this object value)
        {
            return value.ConvertTo(default(T));
        }
        public static T ConvertTo<T>(this object value, T defaultValue)
        {
            if (value != null)
            {
                Type typeFromHandle = typeof(T);
                if (value.GetType() == typeFromHandle)
                {
                    return (T)value;
                }
                TypeConverter converter = TypeDescriptor.GetConverter(value);
                if (converter != null && converter.CanConvertTo(typeFromHandle))
                {
                    return (T)converter.ConvertTo(value, typeFromHandle);
                }
                converter = TypeDescriptor.GetConverter(typeFromHandle);
                if (converter != null && converter.CanConvertFrom(value.GetType()))
                {
                    return (T)converter.ConvertFrom(value);
                }
            }
            return defaultValue;
        }
        public static T ConvertTo<T>(this object value, T defaultValue, bool ignoreException)
        {
            if (ignoreException)
            {
                try
                {
                    T result = value.ConvertTo<T>();
                    return result;
                }
                catch
                {
                    T result = defaultValue;
                    return result;
                }
            }
            return value.ConvertTo<T>();
        }
        public static bool CanConvertTo<T>(this object value)
        {
            if (value != null)
            {
                Type typeFromHandle = typeof(T);
                TypeConverter converter = TypeDescriptor.GetConverter(value);
                if (converter != null && converter.CanConvertTo(typeFromHandle))
                {
                    return true;
                }
                converter = TypeDescriptor.GetConverter(typeFromHandle);
                if (converter != null && converter.CanConvertFrom(value.GetType()))
                {
                    return true;
                }
            }
            return false;
        }
        public static IConverter<T> ConvertTo<T>(this T value)
        {
            return new Converter<T>(value);
        }
    }

}